package model

import (
	"cms/libs"
	"errors"
	"github.com/jinzhu/gorm"
	config "github.com/spf13/viper"
	"math"
	"strings"
)

type Nav struct {
	gorm.Model
	CategoryId   uint   `gorm:"column:category_id" json:"category_id" form:"category_id"`
	ShowPosition uint   `gorm:"column:show_position" json:"show_position" form:"show_position"`
	Url          string `gorm:"column:url" json:"url" form:"url" validate:"required"`
	Title        string `gorm:"column:title" json:"title" form:"title" validate:"required"`
	Desc         string `gorm:"column:desc" json:"desc" form:"desc"`
	From         string `gorm:"column:from" json:"from" form:"from"`
	Image        string `gorm:"column:image" json:"image" form:"image"`
	Keywords     string `gorm:"column:keywords" json:"keywords" form:"keywords"`
	Recommend    string `gorm:"column:recommend" json:"recommend" form:"recommend"`
	Sort         uint   `gorm:"column:sort" json:"sort" form:"sort"`
	Hits         uint   `gorm:"column:hits" json:"hits" form:"hits"`
	Cname        string `gorm:"-" json:"cname" form:"cname"`
}

func (this *Nav) List(page int, params map[string]string) ([]Nav, int, int) {
	var data = []Nav{}
	var totalCount int
	db := libs.DB

	if _, ok := params["title"]; ok && params["title"] != "" {
		db = db.Where("nav.title LIKE ? or nav.keywords LIKE ? or nav.desc LIKE ?", "%"+strings.TrimSpace(params["title"])+"%", "%"+strings.TrimSpace(params["title"])+"%", "%"+strings.TrimSpace(params["title"])+"%")
	}
	if _, ok := params["category_id"]; ok && params["category_id"] != "" {
		db = db.Where("nav.category_id = ?", params["category_id"])
	}
	if _, ok := params["show_position"]; ok && params["show_position"] != "" {
		db = db.Where("nav.show_position = ?", params["show_position"])
	}
	if _, ok := params["re"]; ok && params["re"] != "" {
		db = db.Where("find_in_set(?,nav.recommend)", params["re"])
	}

	limit := config.GetInt("pagination.SearchPageSize")
	offset := (page - 1) * limit
	db.Joins("left join category on nav.category_id = category.id").Find(&data).Count(&totalCount)
	db.Select("nav.*,category.name as cname").Joins("left join category on nav.category_id = category.id").Offset(offset).Limit(limit).Order("id desc").Find(&data)
	totalPages := int(math.Ceil(float64(totalCount) / float64(limit)))
	return data, totalCount, totalPages
}

func (this *Nav) ListCatePage(page int, cid int) ([]Nav, int, int) {
	var data = []Nav{}
	var totalCount int
	db := libs.DB
	limit := config.GetInt("pagination.PageSize")
	offset := (page - 1) * limit
	db.Where("category_id = ? ", cid).Joins("left join category on nav.category_id = category.id").Find(&data).Count(&totalCount)
	db.Where("category_id = ? ", cid).Select("nav.*,category.name as cname").Joins("left join category on nav.category_id = category.id").Offset(offset).Limit(limit).Order("id desc").Find(&data)
	totalPages := int(math.Ceil(float64(totalCount) / float64(limit)))
	return data, totalCount, totalPages
}

func (this *Nav) ListSiteMap(page int) ([]Nav, int, int) {
	var data = []Nav{}
	var totalCount int
	db := libs.DB
	limit := 1000
	offset := (page - 1) * limit
	db.Find(&data).Count(&totalCount)
	db.Offset(offset).Limit(limit).Order("id desc").Find(&data)
	totalPages := int(math.Ceil(float64(totalCount) / float64(limit)))
	return data, totalCount, totalPages
}

func (this *Nav) ListCate(cid int) *[]Nav {
	var data = []Nav{}
	db := libs.DB
	db.Where("category_id = ? ", cid).Offset(0).Limit(100).Order("id desc").Find(&data)
	return &data
}

func (this *Nav) ListRecommend(id int) []Nav {
	var data = []Nav{}
	db := libs.DB
	db.Where("find_in_set(?,recommend) ", id).Order("id desc").Find(&data)
	return data
}

func (this *Nav) ListNews() []Nav {
	var data = []Nav{}
	db := libs.DB
	db.Where("category_id != ?", "").Offset(0).Limit(20).Order("id desc").Find(&data)
	return data
}

func (this *Nav) SearchList(ids []string) []Nav {
	var data = []Nav{}
	db := libs.DB
	db.Where("id in (?)", ids).Order("id desc").Find(&data)
	return data
}

func (this *Nav) Info(id uint) (Nav, error) {
	var nav Nav
	db := libs.DB

	if db.Where("id = ?", id).First(&nav).RecordNotFound() {
		return Nav{}, errors.New("内容未找到")
	}
	return nav, nil
}

func (this *Nav) Last() (Nav, error) {
	var nav Nav
	db := libs.DB
	db.Last(&nav)
	return nav, nil
}

func (this *Nav) LastMore(id uint) []Nav {
	var data = []Nav{}
	db := libs.DB
	db.Where("id > ?", id).Order("id desc").Find(&data)
	return data
}

func (this *Nav) Add(postValues map[string][]string, filePath string) error {
	var nav Nav
	db := libs.DB

	if err := libs.FormDecode(&nav, postValues); err != nil {
		return err
	}
	if err := libs.Validate(nav); err != nil {
		return err
	}
	if !db.Where("title = ? ", nav.Title).First(&Nav{}).RecordNotFound() {
		return errors.New("该标题已经存在")
	}

	if filePath != "" {
		nav.Image = filePath
	}
	nav.From = "手动添加"

	nav.Recommend = strings.Join(postValues["recommend"], ",")

	if err := db.Create(&nav).Error; err != nil {
		return err
	}
	return nil
}

func (this *Nav) Update(postValues map[string][]string, filePath string) error {
	var nav Nav
	var nav2 Nav
	db := libs.DB

	if err := libs.FormDecode(&nav, postValues); err != nil {
		return err
	}
	if err := libs.Validate(nav); err != nil {
		return err
	}
	if !db.Where("title = ? and id != ?", nav.Title, nav.ID).First(&Nav{}).RecordNotFound() {
		return errors.New("该标题已经存在")
	}
	if db.Where("id = ? ", nav.ID).First(&nav2).RecordNotFound() {
		return errors.New("未查询到内容id")
	}

	if filePath != "" {
		nav.Image = filePath
	} else {
		nav.Image = nav2.Image
	}
	nav.From = "手动添加"

	nav.Recommend = strings.Join(postValues["recommend"], ",")

	if err := db.Save(&nav).Error; err != nil {
		return err
	}
	return nil
}

func (this *Nav) Del(id uint) error {
	var nav Nav
	db := libs.DB
	if err := db.Unscoped().Where("id = ?", id).Delete(&nav).Error; err != nil {
		return err
	}
	return nil
}

func (this *Nav) DelAll(id string) error {
	var nav Nav
	db := libs.DB
	if err := db.Unscoped().Where("id in (?)", strings.Split(id, ",")).Delete(&nav).Error; err != nil {
		return err
	}
	return nil
}

func (this *Nav) UpdateHitsNum(id uint) error {
	db := libs.DB
	return db.Model(&Nav{}).Where("id = ?", id).UpdateColumn("hits", gorm.Expr("hits + ?", 1)).Error
}
